<?php

namespace apps\admin\listeners;
if( !defined( 'APP_ROOT' ) ){ echo 'Direct Access Deny!'; return; }

use \Phalcon\Events\Event;
use \Phalcon\Mvc\Dispatcher;
use \Phalcon\Mvc\User\Plugin;
use enums\LogEnums;
use enums\QueueEnums;
// use vendors\SeasLog\SeasLog;

class DispatcherListener extends Plugin
{
		
	public function beforeExecuteRoute( Event $event, Dispatcher $dispatcher )
	{ // set acl
	    
	    
	}

	public function beforeException( Event $event, Dispatcher $dispatcher, \Exception $exception )
	{
	    if( APP_MODE != 'production' )
	    {
	        throw $exception;
	    }
	    else
	    {
	        file_put_contents( APP_ROOT . '/logs/php_error_log.txt', $exception->getMessage() . ' | ' . $exception->getTraceAsString() . PHP_EOL, FILE_APPEND );
	    }
	    
		if( isset( $_SERVER[ 'HTTP_X_REQUESTED_WITH' ] ) )
		{ // ajax request
			return;
		}
		
		// if( $SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' );
		// strtolower(
		
		$dispatcher->forward( array(
				'module' => 'admin',
				'controller' => 'error',
				'action' => 'err404' 
		) );
		
		return false;
	}

	/**
	 * @author( author = 'Carey' )
	 * @date( date = '2015.8.31' )
	 * @comment( comment = 'session安全,后台用户操作日志' )
	 * @method( method = 'beforeDispatchLoop' )
	 * @op( op = '' )
	 */
	public function beforeDispatchLoop( Event $event, Dispatcher $dispatcher )
	{
		$keyParams = array();
		$params = $dispatcher->getParams();
		
		foreach( $params as $k => $v )
		{
			if( $k & 1 )
			{
				$keyParams[ $params[ $k - 1 ]] = $v;
			}
		}
		
		$dispatcher->setParams( $keyParams );
		
		//session 安全管理 ( 浏览器 + ip地址 )
		$adminUserInfo = $this->session->get( 'userInfo' );
		if( !$adminUserInfo )
		{
			//用户未登录或者访问用户session信息出错 
			return;
		}
		
		$strVerfiy = trim( $_SERVER[ 'HTTP_USER_AGENT' ] ) . trim( $_SERVER[ 'REMOTE_ADDR' ] );
		if( $adminUserInfo[ 'session_verfiy' ] != $strVerfiy )
		{//session_id + ip / session_id + browser 验证失败  写入日志
//			$this->queue->put( array(
//					'type' => LogEnums::LOG_ADMIN_SESSION_LOG,
//					'body' => array(
//							'userId' => $adminUserInfo['id'],
//							'userName' => $adminUserInfo['loginname'],
//							'addTime' => $_SERVER['REQUEST_TIME'],
//							'url' 	=> $_SERVER['REQUEST_URI']
//					)
//			));
			return;
		}
			
		$adminRegTime = $this->config[ 'admin_regenrator_time_interval' ];
		$currTime = intval( $_SERVER[ 'REQUEST_TIME' ] - $adminUserInfo[ 'admin_regenrator_time' ] );
		if( $currTime >= $adminRegTime )
		{//过期   ---  重新生成
			//session_regenerate_i2d();
			$strVerfiy = trim( $_SERVER[ 'HTTP_USER_AGENT' ] ). trim( $_SERVER[ 'REMOTE_ADDR' ] );
			$adminUserInfo[ 'admin_regenrator_time' ]	= $_SERVER[ 'REQUEST_TIME' ];
			$adminUserInfo[ 'session_verfiy' ] 			= $strVerfiy;
			
			$this->session->set( 'userInfo', $adminUserInfo );
		}
		
		//记录后台操作日志
// 	   return $this->_sendLog( $dispatcher , $adminUserInfo );
	}
	
	
	/**
	 * 记录平台用户/代理商用户操作日志
	 * @param Dispatcher $dispatcher
	 * @param unknown $adminUserInfo
	 */
	private function _sendLog( $dispatcher, $adminUserInfo )
	{
	    $controller = strtolower( $dispatcher->getControllerName() ) . 'controller';
	    $method = strtolower( $dispatcher->getActionName() ) . 'action';
	    
	    $annotation =  $this->dataCache->get( 'admin_' . $controller . '_' . $method . '_cache' );
	    if( !$annotation || empty( $annotation ) )
	    {
	        //缓存注释信息读取失败 重新去文件中读取
	       $annotation = $this->_cacheAnnotation( $dispatcher, $controller , $method );
	    }
	    if( empty( $annotation ) || !isset( $annotation[ 'op' ] ) )
	        return;
	    
	    $arrOperation = array( 'c' , 'u' , 'd' );
	    //cud操作记录于用户操作日志 ; 其他则忽略
	    $op = $annotation[ 'op' ];
	    if( in_array( $op, $arrOperation ) )
	    {
	        $isAjax = 0;
	        if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
	        {
	            $isAjax = 1;
	        }
	        
	        $arrParams[ 'type' ] = LogEnums::LOG_TYPE_USER_OPT;
            $arrParams[ 'userId' ] = $adminUserInfo[ 'id' ];
            $arrParams[ 'userName' ] =  $adminUserInfo[ 'loginname' ];
            $arrParams[ 'controller' ] = $controller;
            $arrParams[ 'action' ] = $method;
            $arrParams[ 'operation' ] = $op;
            $arrParams[ 'url' ] = 'http://' .$_SERVER[ 'SERVER_NAME' ] . $_SERVER['REQUEST_URI'];
            $arrParams[ 'comment' ] =  $annotation[ 'comment' ];
            $arrParams[ 'user_agent' ] = $_SERVER[ 'HTTP_USER_AGENT' ];
            $arrParams[ 'is_ajax' ] = $isAjax;
            $arrParams[ 'remote_addr' ] = $_SERVER[ 'REMOTE_ADDR' ];
            $arrParams[ 'request_method' ] = $_SERVER[ 'REQUEST_METHOD' ];
            $arrParams[ 'request_time' ] = $_SERVER[ 'REQUEST_TIME' ];
            $arrParams[ 'request_time_float' ] = $_SERVER[ 'REQUEST_TIME_FLOAT' ];
            
            if( $_POST && !empty( $_POST ) )
                $arrParams[ 'postContent' ] = $_POST;
            
            if( isset( $_SERVER['HTTP_REFERER'] ) )            
                $arrParams[ 'referer' ] = $_SERVER['HTTP_REFERER'];
            
            $arrParams = $this->rqueue->getMsgProto( $arrParams,
                QueueEnums::QUEUE_USER_LOG,
                $msgt = QueueEnums::MSGTYPE_ARRAY,
                'Logs',
                'defaultOp',
                $id = false,
                $priority = QueueEnums::PRIORITY_MEDIUM
            );
            
            $this->rqueue->push( $arrParams );
	    }
	    else
	    {
	        $server = serialize( $_SERVER );
	        if( isset( $_POST ) && !empty( $_POST ) )
	            $post = serialize( $_POST );
	        else
	            $post = '';
	        
	        $strParams = '';
    		if( isset( $_SERVER[ 'REMOTE_ADDR' ] ) )
    		{
    		    $remote_addr = $_SERVER[ 'REMOTE_ADDR' ];
    		}
    		else
    		{
    		    $remote_addr = '';
    		}
    		if( isset( $_SERVER[ 'HTTP_USER_AGENT' ] ) )
    		{
    		    $user_agent = serialize( $_SERVER[ 'HTTP_USER_AGENT' ] );
    		}
    		else
    		{
    		    $user_agent = '';
    		}
    		
    		if( isset( $annotation[ 'comment' ] ) )
    		    $comment = $annotation[ 'comment' ];
    		else
    		    $comment = '';
    		
	        $strParams = $user_agent .'#'. $remote_addr . '#' . $server . '#' . $post . '#' .strtolower( $dispatcher->getControllerName() ) . '#' .  strtolower( $dispatcher->getActionName() ) . '#' . $comment ;
	        try{
	          // $this->seasLog->log( SEASLOG_INFO, trim( $strParams ) );
	        }
	        catch ( \Exception $e ) 
	        {
	            echo $e->getMessage();
	            return;
	        }
	    }
	    return true;
	}
	
    /**
     * 如果不存在 annotation 信息立马缓存
     * @param unknown $c
     * @param unknown $a
     */
	private function _cacheAnnotation( $dispatcher, $c, $a )
	{
	    
        if( !$dispatcher || !$c || !$a  )
            return false;
        
        $strClassName = $dispatcher->getControllerClass();
        $strActionName = $dispatcher->getActiveMethod();
        $annInfo = $this->annotations->getMethod( $strClassName , $strActionName );
	    if( $annInfo && !empty( $annInfo ) )
	    {
	        
	        $arrAnnInfo = array();
	        foreach ( $annInfo as $info )
	        {
	            $arrAnnInfo[ $info->getName() ] = $info->getNamedArgument( $info->getName() );
	        }
	        $this->dataCache->save( 'admin_' . $c . '_' . $a . '_cache', $arrAnnInfo );
	        
	        return $arrAnnInfo;
	    }
	    else 
	        return false;
	  
	}
}